package com.zatech.cgnci.project.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zatech.cgnci.project.base.context.UserContext;
import com.zatech.cgnci.project.base.enums.ResponseCodeEnum;
import com.zatech.cgnci.project.base.enums.ValueDataTypeEnum;
import com.zatech.cgnci.project.base.exception.GlobalException;
import com.zatech.cgnci.project.base.utils.ConvertUtils;
import com.zatech.cgnci.project.base.utils.DownloadTemplateHelper;
import com.zatech.cgnci.project.base.utils.VerifyUtils;
import com.zatech.cgnci.project.dto.CgnciCodeTypeAddDTO;
import com.zatech.cgnci.project.dto.CgnciCodeTypeQueryDTO;
import com.zatech.cgnci.project.dto.CgnciCodeTypeUpdateDTO;
import com.zatech.cgnci.project.entity.CgnciCodeTypeDO;
import com.zatech.cgnci.project.entity.ExcelHeader;
import com.zatech.cgnci.project.entity.UserEntity;
import com.zatech.cgnci.project.mapper.CgnciCodeTypeMapper;
import com.zatech.cgnci.project.service.CgnciCodeTypeService;
import com.zatech.cgnci.project.vo.AllCgnciCodeTypeVO;
import com.zatech.cgnci.project.vo.CgnciCodeTypeVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 基础信息表 服务实现类
 * </p>
 *
 * @author Generator
 * @since 2024-12-17
 */
@Slf4j
@Service
public class CgnciCodeTypeServiceImpl extends ServiceImpl<CgnciCodeTypeMapper, CgnciCodeTypeDO> implements CgnciCodeTypeService {
    @Resource
    private CgnciCodeTypeMapper codeTypeMapper;

    @Override
    public IPage<CgnciCodeTypeVO> pageHigherCode(CgnciCodeTypeQueryDTO queryDTO) {
        return codeTypeMapper.pageHigherCode(queryDTO.toPage(), queryDTO);
    }

    @Override
    public IPage<CgnciCodeTypeVO> pageCode(CgnciCodeTypeQueryDTO queryDTO) {
        return codeTypeMapper.pageCode(queryDTO.toPage(), queryDTO);
    }

    @Override
    public void addCode(CgnciCodeTypeAddDTO codeTypeAddDTO) {
        // 获取当前登录用户
        UserEntity user = UserContext.getUser();
        List<CgnciCodeTypeDO> list = this.list(new LambdaQueryWrapper<CgnciCodeTypeDO>()
                .eq(CgnciCodeTypeDO::getCodeHigherLevelCode, codeTypeAddDTO.getCodeHigherLevelCode()));
        if (VerifyUtils.isNotEmpty(list)) {
            throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR, "已存在相同的上级编码");
        }
        List<CgnciCodeTypeAddDTO.SubCodeTypeDTO> subCodeTypeDTOList = codeTypeAddDTO.getSubCodeTypeDTOList();
        subCodeTypeDTOList.forEach(sub -> {
            CgnciCodeTypeDO codeTypeDO = ConvertUtils.convert(sub, CgnciCodeTypeDO.class);
            codeTypeDO.setCodeHigherLevelCode(codeTypeAddDTO.getCodeHigherLevelCode());
            codeTypeDO.setCodeHigherLevelName(codeTypeAddDTO.getCodeHigherLevelName());
            codeTypeDO.setCreateUserName(user.getNameAndCode());
            codeTypeDO.setUpdateUserName(user.getNameAndCode());
            this.save(codeTypeDO);
        });
    }

    @Override
    public void updateCode(CgnciCodeTypeUpdateDTO codeTypeUpdateDTO) {
        // 获取当前登录用户
        UserEntity user = UserContext.getUser();
        List<CgnciCodeTypeUpdateDTO.SubCodeTypeDTO> subCodeTypeDTOList = codeTypeUpdateDTO.getSubCodeTypeDTOList();
        Set<Long> codeIds = subCodeTypeDTOList.stream().map(CgnciCodeTypeUpdateDTO.SubCodeTypeDTO::getCodeId).filter(VerifyUtils::isNotEmpty).collect(Collectors.toSet());
        List<CgnciCodeTypeDO> list = this.list(new LambdaQueryWrapper<CgnciCodeTypeDO>()
                .eq(CgnciCodeTypeDO::getCodeHigherLevelCode, codeTypeUpdateDTO.getCodeHigherLevelCode())
                .notIn(VerifyUtils.isNotEmpty(codeIds), CgnciCodeTypeDO::getCodeId, codeIds));
        if (VerifyUtils.isNotEmpty(list)) {
            throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR, "已存在相同的上级编码");
        }

        subCodeTypeDTOList.forEach(sub -> {
            CgnciCodeTypeDO codeTypeDO = ConvertUtils.convert(sub, CgnciCodeTypeDO.class);
            codeTypeDO.setCodeHigherLevelCode(codeTypeUpdateDTO.getCodeHigherLevelCode());
            codeTypeDO.setCodeHigherLevelName(codeTypeUpdateDTO.getCodeHigherLevelName());
            if (VerifyUtils.isEmpty(codeTypeDO.getCodeId())) {
                codeTypeDO.setCreateUserName(user.getNameAndCode());
                codeTypeDO.setUpdateUserName(user.getNameAndCode());
                this.save(codeTypeDO);
                return;
            }
            codeTypeDO.setUpdateUserName(user.getNameAndCode());
            this.updateById(codeTypeDO);
        });
    }

    @Override
    public String getBusinessNo(String codeHigherLevelCode, String codeName) {
        CgnciCodeTypeDO cgnciCodeTypeDO = this.getOne(new LambdaQueryWrapper<CgnciCodeTypeDO>()
                .eq(CgnciCodeTypeDO::getCodeHigherLevelCode, codeHigherLevelCode)
                .eq(CgnciCodeTypeDO::getCodeName, codeName));
        String codeCode = cgnciCodeTypeDO.getCodeCode();
        codeCode = String.format("%04d", Integer.parseInt(codeCode) + 1);
        cgnciCodeTypeDO.setCodeCode(codeCode);
        this.updateById(cgnciCodeTypeDO);
        return codeCode;
    }

    @Override
    public Map<String, List<AllCgnciCodeTypeVO>> queryAll() {
        List<AllCgnciCodeTypeVO> allCgnciCodeTypeVOS = codeTypeMapper.queryAllCodeShorthand();
        Map<String, List<AllCgnciCodeTypeVO>> collect = allCgnciCodeTypeVOS.stream().collect(Collectors.groupingBy(AllCgnciCodeTypeVO::getCodeHigherLevelCode));
        if (!collect.isEmpty()) {
            return collect;
        }
        return Collections.emptyMap();
    }

    @Autowired
    DownloadTemplateHelper downloadTemplateHelper;

    //todo 暂时支持功能，后续考虑表头是否从数据库获取
    @Override
    public void downloadTemplate(HttpServletResponse response) {
        String templateName = "基础代码批量导入模板.xlsx";
        List<ExcelHeader> excelHeaders = new ArrayList<>();
        List<String> nameList = new ArrayList<>();
        nameList.add("生效");
        nameList.add("失效");
        excelHeaders.add(ExcelHeader.builder().code("serial").sheetName("sheet1").sheetNo(1)
                .name("序号").exampleValue("样例数据不可更改数据从第三行开始识别").valueDataType(ValueDataTypeEnum.INSURED_FACTOR_NUMBER.getCode()).build());
        excelHeaders.add(ExcelHeader.builder().sheetName("sheet1").sheetNo(1)
                .name("基础代码编号").required(true).maxLength(8).repeatCheck(true).valueDataType(ValueDataTypeEnum.INSURED_FACTOR_STRING.getCode()).build());
        excelHeaders.add(ExcelHeader.builder().sheetName("sheet1").sheetNo(1)
                .name("基础代码名称").required(true).repeatCheck(true).valueDataType(ValueDataTypeEnum.INSURED_FACTOR_STRING.getCode()).build());
        excelHeaders.add(ExcelHeader.builder().sheetName("sheet1").sheetNo(1)
                .name("码值编号").required(true).valueDataType(ValueDataTypeEnum.INSURED_FACTOR_STRING.getCode()).build());
        excelHeaders.add(ExcelHeader.builder().sheetName("sheet1").sheetNo(1)
                .name("码值名称").required(true).valueDataType(ValueDataTypeEnum.INSURED_FACTOR_STRING.getCode()).build());
        excelHeaders.add(ExcelHeader.builder().sheetName("sheet1").sheetNo(1).required(true)
                .name("状态").optionList(nameList).valueDataType(ValueDataTypeEnum.INSURED_FACTOR_ENUM.getCode()).build());
        excelHeaders.add(ExcelHeader.builder().sheetName("sheet1").sheetNo(1)
                .name("出单机构场景").valueDataType(ValueDataTypeEnum.INSURED_FACTOR_STRING.getCode()).build());
        downloadTemplateHelper.createExcelTemplate(response, templateName, excelHeaders);
    }

    @Override
    public CgnciCodeTypeVO getCodeTypeByCode(String codeHigherLevelCode, String codeCode) {
        CgnciCodeTypeDO cgnciCodeTypeDO = this.getOne(new LambdaQueryWrapper<CgnciCodeTypeDO>()
                .eq(CgnciCodeTypeDO::getCodeHigherLevelCode, codeHigherLevelCode)
                .eq(CgnciCodeTypeDO::getCodeName, codeCode));
        return ConvertUtils.convert(cgnciCodeTypeDO, CgnciCodeTypeVO.class);
    }
}
